import { Response } from 'express';
import { FileRequest } from '../types/file-request';
import { AuthenticatedRequest } from '../types/auth';
import { TransactionClient } from '../types/prisma-types';
import { ApiError } from '../utils/ApiError';
import { StatusCodes } from '../constants/statusCodes';
import { logger } from '../utils/logger';
import prisma from '../lib/prisma';
import * as fs from 'fs/promises';
import * as path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);

export const dataManagementController = {
  // 导出系统数据
  async exportData(req: AuthenticatedRequest, res: Response) {
    try {
      if (!req.user) {
        throw new ApiError(StatusCodes.UNAUTHORIZED, '未授权访问');
      }

      const { type } = req.query;
      let data;

      switch (type) {
        case 'users':
          data = await prisma.user.findMany({
            select: {
              id: true,
              name: true,
              email: true,
              role: true,
              createdAt: true,
              updatedAt: true
            }
          });
          break;
        case 'teaching-points':
          data = await prisma.teachingPoint.findMany({
            where: { deleted: false }
          });
          break;
        case 'evaluations':
          data = await prisma.evaluation.findMany({
            include: {
              questions: true
            }
          });
          break;
        default:
          throw new ApiError(StatusCodes.BAD_REQUEST, '不支持的数据类型');
      }

      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const filename = `${String(type)}_${timestamp}.json`;
      const exportPath = path.join(process.env.DATA_EXPORT_PATH || 'exports', filename);

      await fs.mkdir(path.dirname(exportPath), { recursive: true });
      await fs.writeFile(exportPath, JSON.stringify(data, null, 2));

      logger.info('Data exported successfully', { type, filename });
      res.download(exportPath, filename);
    } catch (error) {
      logger.error('Error exporting data', { error });
      throw error;
    }
  },

  // 导入系统数据
  async importData(req: FileRequest, res: Response) {
    try {
      if (!req.user) {
        throw new ApiError(StatusCodes.UNAUTHORIZED, '未授权访问');
      }

      if (!req.file) {
        throw new ApiError(StatusCodes.BAD_REQUEST, '没有找到上传的文件');
      }

      const { type } = req.body;
      const data = JSON.parse(await fs.readFile(req.file.path, 'utf-8'));

      await prisma.$transaction(async (tx: TransactionClient) => {
        switch (type) {
          case 'users':
            for (const user of data) {
              await tx.user.upsert({
                where: { email: user.email },
                update: user,
                create: user
              });
            }
            break;
          case 'teaching-points':
            for (const point of data) {
              await tx.teachingPoint.upsert({
                where: { code: point.code },
                update: point,
                create: point
              });
            }
            break;
          case 'evaluations':
            for (const evaluation of data) {
              const { questions, ...evalData } = evaluation;
              await tx.evaluation.upsert({
                where: { id: evaluation.id },
                update: {
                  ...evalData,
                  questions: {
                    connect: questions.map((q: any) => ({ id: q.id }))
                  }
                },
                create: {
                  ...evalData,
                  questions: {
                    connect: questions.map((q: any) => ({ id: q.id }))
                  }
                }
              });
            }
            break;
          default:
            throw new ApiError(StatusCodes.BAD_REQUEST, '不支持的数据类型');
        }
      });

      // 清理临时文件
      await fs.unlink(req.file.path);

      logger.info('Data imported successfully', { type });
      res.json({ message: '数据导入成功' });
    } catch (error) {
      logger.error('Error importing data', { error });
      if (req.file) {
        await fs.unlink(req.file.path).catch(() => {});
      }
      throw error;
    }
  },

  // 备份数据库
  async backupDatabase(req: AuthenticatedRequest, res: Response) {
    try {
      if (!req.user) {
        throw new ApiError(StatusCodes.UNAUTHORIZED, '未授权访问');
      }

      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const backupPath = path.join(process.env.BACKUP_PATH || 'backups', `backup_${timestamp}.sql`);

      await fs.mkdir(path.dirname(backupPath), { recursive: true });

      const { stdout, stderr } = await execAsync(
        `pg_dump -h ${process.env.DB_HOST} -U ${process.env.DB_USER} -d ${process.env.DB_NAME} -F c -f ${backupPath}`
      );

      if (stderr) {
        logger.error('Database backup warning', { stderr });
      }

      logger.info('Database backup completed', { backupPath, stdout });
      res.json({ message: '数据库备份成功', backupPath });
    } catch (error) {
      logger.error('Error backing up database', { error });
      throw new ApiError(StatusCodes.INTERNAL_SERVER_ERROR, '数据库备份失败');
    }
  },

  // 恢复数据库
  async restoreDatabase(req: AuthenticatedRequest, res: Response) {
    try {
      if (!req.user) {
        throw new ApiError(StatusCodes.UNAUTHORIZED, '未授权访问');
      }

      const { backupFile } = req.body;
      const backupPath = path.join(process.env.BACKUP_PATH || 'backups', backupFile);

      // 验证备份文件是否存在
      try {
        await fs.access(backupPath);
      } catch {
        throw new ApiError(StatusCodes.NOT_FOUND, '备份文件不存在');
      }

      // 执行恢复
      const { stdout, stderr } = await execAsync(
        `pg_restore -h ${process.env.DB_HOST} -U ${process.env.DB_USER} -d ${process.env.DB_NAME} -c ${backupPath}`
      );

      if (stderr) {
        logger.error('Database restore warning', { stderr });
      }

      logger.info('Database restore completed', { backupFile, stdout });
      res.json({ message: '数据库恢复成功' });
    } catch (error) {
      logger.error('Error restoring database', { error });
      throw new ApiError(StatusCodes.INTERNAL_SERVER_ERROR, '数据库恢复失败');
    }
  },

  // 获取备份文件列表
  async getBackupFiles(_req: AuthenticatedRequest, res: Response) {
    try {
      const backupDir = process.env.BACKUP_PATH || 'backups';
      await fs.mkdir(backupDir, { recursive: true });

      const files = await fs.readdir(backupDir);
      const backupFiles = await Promise.all(
        files.map(async (file) => {
          const filePath = path.join(backupDir, file);
          const stats = await fs.stat(filePath);
          return {
            name: file,
            size: stats.size,
            createdAt: stats.birthtime
          };
        })
      );

      // 按创建时间降序排序
      backupFiles.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());

      res.json(backupFiles);
    } catch (error) {
      logger.error('Error getting backup files', { error });
      throw new ApiError(StatusCodes.INTERNAL_SERVER_ERROR, '获取备份文件列表失败');
    }
  }
};
